home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / crt / sun4.md / gmon.c < prev    next >
C/C++ Source or Header  |  1990-11-08  |  10KB  |  434 lines

  1. #ifndef lint
  2. static    char sccsid[] = "@(#)gmon.c 1.1 86/02/03 SMI";
  3. #endif
  4.  
  5. #ifdef DEBUG
  6. #include <stdio.h>
  7. #endif DEBUG
  8.  
  9. #include "gmon.h"
  10.  
  11.     /*
  12.      *    froms is actually a bunch of unsigned shorts indexing tos
  13.      */
  14. extern char        profiling;
  15.  
  16. unsigned short    *froms;
  17. struct tostruct    *tos = 0;
  18. long        tolimit = 0;
  19. char        *s_lowpc = 0;
  20. char        *s_highpc = 0;
  21. unsigned long    s_textsize = 0;
  22. int        s_scale;
  23. char        *minsbrk = 0;
  24.  
  25. static int    ssiz;
  26. static int    *sbuf;
  27.  
  28. #define    MSG "No space for monitor buffer(s)\n"
  29.  
  30. monstartup(lowpc, highpc)
  31.     char    *lowpc;
  32.     char    *highpc;
  33. {
  34.     int            monsize;
  35.     char        *buffer;
  36.     char        *sbrk();
  37.  
  38.     /*
  39.      *    round lowpc and highpc to multiples of the density we're using
  40.      *    so the rest of the scaling (here and in gprof) stays in ints.
  41.      */
  42.     lowpc = (char *)
  43.         ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
  44.     s_lowpc = lowpc;
  45.     highpc = (char *)
  46.         ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
  47.     s_highpc = highpc;
  48.     s_textsize = highpc - lowpc;
  49.     monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
  50.     buffer = sbrk( monsize );
  51.     if ( buffer == (char *) -1 ) {
  52.     write( 2 , MSG , sizeof(MSG) );
  53.     return;
  54.     }
  55.     froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
  56.     if ( froms == (unsigned short *) -1 ) {
  57.     write( 2 , MSG , sizeof(MSG) );
  58.     froms = 0;
  59.     return;
  60.     }
  61.     tolimit = s_textsize * ARCDENSITY / 100;
  62.     if ( tolimit < MINARCS ) {
  63.     tolimit = MINARCS;
  64.     } else if ( tolimit > 65534 ) {
  65.     tolimit = 65534;
  66.     }
  67.     tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
  68.     if ( tos == (struct tostruct *) -1 ) {
  69.     write( 2 , MSG , sizeof(MSG) );
  70.     froms = 0;
  71.     tos = 0;
  72.     return;
  73.     }
  74.     minsbrk = sbrk(0);
  75.     tos[0].link = 0;
  76.     monitor( lowpc , highpc , buffer , monsize , tolimit );
  77. }
  78.  
  79. _mcleanup()
  80. {
  81.     int            fd;
  82.     int            fromindex;
  83.     int            endfrom;
  84.     char        *frompc;
  85.     int            toindex;
  86.     struct rawarc    rawarc;
  87.  
  88.     moncontrol(0);
  89.     fd = creat( "gmon.out" , 0666 );
  90.     if ( fd < 0 ) {
  91.     perror( "mcount: gmon.out" );
  92.     return;
  93.     }
  94. #   ifdef DEBUG
  95.     fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
  96. #   endif DEBUG
  97.     write( fd , sbuf , ssiz );
  98.     endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
  99.     for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
  100.     if ( froms[fromindex] == 0 ) {
  101.         continue;
  102.     }
  103.     frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
  104.     for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
  105. #        ifdef DEBUG
  106.         fprintf( stderr ,
  107.             "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
  108.             frompc , tos[toindex].selfpc , tos[toindex].count );
  109. #        endif DEBUG
  110.         rawarc.raw_frompc = (unsigned long) frompc;
  111.         rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
  112.         rawarc.raw_count = tos[toindex].count;
  113.         write( fd , &rawarc , sizeof rawarc );
  114.     }
  115.     }
  116.     close( fd );
  117. }
  118.  
  119. #if vax
  120.  
  121. asm(".text");
  122. asm("#the beginning of mcount()");
  123. asm(".data");
  124. mcount()
  125. {
  126.     register char            *selfpc;    /* r11 => r5 */
  127.     register unsigned short        *frompcindex;    /* r10 => r4 */
  128.     register struct tostruct    *top;        /* r9  => r3 */
  129.     register struct tostruct    *prevtop;    /* r8  => r2 */
  130.     register long            toindex;    /* r7  => r1 */
  131.  
  132. #ifdef lint
  133.     selfpc = (char *)0;
  134.     frompcindex = 0;
  135. #else not lint
  136.     /*
  137.      *    find the return address for mcount,
  138.      *    and the return address for mcount's caller.
  139.      */
  140.     asm("    .text");        /* make sure we're in text space */
  141.     asm("    movl (sp), r11");    /* selfpc = ... (jsb frame) */
  142.     asm("    movl 16(fp), r10");    /* frompcindex =     (calls frame) */
  143. #endif not lint
  144.     /*
  145.      *    check that we are profiling
  146.      *    and that we aren't recursively invoked.
  147.      */
  148.     if (profiling) {
  149.         goto out;
  150.     }
  151.     profiling++;
  152.     /*
  153.      *    check that frompcindex is a reasonable pc value.
  154.      *    for example:    signal catchers get called from the stack,
  155.      *            not from text space.  too bad.
  156.      */
  157.     frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
  158.     if ((unsigned long)frompcindex > s_textsize) {
  159.         goto done;
  160.     }
  161.     frompcindex =
  162.         &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
  163.     toindex = *frompcindex;
  164.     if (toindex == 0) {
  165.         /*
  166.          *    first time traversing this arc
  167.          */
  168.         toindex = ++tos[0].link;
  169.         if (toindex >= tolimit) {
  170.             goto overflow;
  171.         }
  172.         *frompcindex = toindex;
  173.         top = &tos[toindex];
  174.         top->selfpc = selfpc;
  175.         top->count = 1;
  176.         top->link = 0;
  177.         goto done;
  178.     }
  179.     top = &tos[toindex];
  180.     if (top->selfpc == selfpc) {
  181.         /*
  182.          *    arc at front of chain; usual case.
  183.          */
  184.         top->count++;
  185.         goto done;
  186.     }
  187.     /*
  188.      *    have to go looking down chain for it.
  189.      *    top points to what we are looking at,
  190.      *    prevtop points to previous top.
  191.      *    we know it is not at the head of the chain.
  192.      */
  193.     for (; /* goto done */; ) {
  194.         if (top->link == 0) {
  195.             /*
  196.              *    top is end of the chain and none of the chain
  197.              *    had top->selfpc == selfpc.
  198.              *    so we allocate a new tostruct
  199.              *    and link it to the head of the chain.
  200.              */
  201.             toindex = ++tos[0].link;
  202.             if (toindex >= tolimit) {
  203.                 goto overflow;
  204.             }
  205.             top = &tos[toindex];
  206.             top->selfpc = selfpc;
  207.             top->count = 1;
  208.             top->link = *frompcindex;
  209.             *frompcindex = toindex;
  210.             goto done;
  211.         }
  212.         /*
  213.          *    otherwise, check the next arc on the chain.
  214.          */
  215.         prevtop = top;
  216.         top = &tos[top->link];
  217.         if (top->selfpc == selfpc) {
  218.             /*
  219.              *    there it is.
  220.              *    increment its count
  221.              *    move it to the head of the chain.
  222.              */
  223.             top->count++;
  224.             toindex = prevtop->link;
  225.             prevtop->link = top->link;
  226.             top->link = *frompcindex;
  227.             *frompcindex = toindex;
  228.             goto done;
  229.         }
  230.  
  231.     }
  232. done:
  233.     profiling--;
  234.     /* and fall through */
  235. out:
  236.     asm("    rsb");
  237.  
  238. overflow:
  239.     profiling++; /* halt further profiling */
  240. #   define    TOLIMIT    "mcount: tos overflow\n"
  241.     write(2, TOLIMIT, sizeof(TOLIMIT));
  242.     goto out;
  243. }
  244. asm(".text");
  245. asm("#the end of mcount()");
  246. asm(".data");
  247.  
  248. #endif vax
  249.  
  250. /*VARARGS1*/
  251. monitor( lowpc , highpc , buf , bufsiz , nfunc )
  252.     char    *lowpc;
  253.     char    *highpc;
  254.     int        *buf, bufsiz;
  255.     int        nfunc;    /* not used, available for compatability only */
  256. {
  257.     register o;
  258.  
  259.     if ( lowpc == 0 ) {
  260.     moncontrol(0);
  261.     _mcleanup();
  262.     return;
  263.     }
  264.     sbuf = buf;
  265.     ssiz = bufsiz;
  266.     ( (struct phdr *) buf ) -> lpc = lowpc;
  267.     ( (struct phdr *) buf ) -> hpc = highpc;
  268.     ( (struct phdr *) buf ) -> ncnt = ssiz;
  269.     o = sizeof(struct phdr);
  270.     buf = (int *) ( ( (int) buf ) + o );
  271.     bufsiz -= o;
  272.     if ( bufsiz <= 0 )
  273.     return;
  274.     o = ( ( (char *) highpc - (char *) lowpc) );
  275.     if( bufsiz < o )
  276.     s_scale = ( (float) bufsiz / o ) * 65536;
  277.     else
  278.     s_scale = 65536;
  279.     moncontrol(1);
  280. }
  281.  
  282. /*
  283.  * Control profiling
  284.  *    profiling is what mcount checks to see if
  285.  *    all the data structures are ready.
  286.  */
  287. moncontrol(mode)
  288.     int mode;
  289. {
  290.     if (mode) {
  291.     /* start */
  292.     profil((char*) sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
  293.         s_lowpc, s_scale);
  294.     profiling = 0;
  295.     } else {
  296.     /* stop */
  297.     profil((char *)0, 0, 0, 0);
  298.     profiling = 3;
  299.     }
  300. }
  301.  
  302.  
  303. #if vax
  304.  
  305. /*
  306.  * This is a stub for the "brk" system call, which we want to
  307.  * catch so that it will not deallocate our data space.
  308.  * (of which the program is not aware)
  309.  */
  310. extern char *curbrk;
  311.  
  312. brk(addr)
  313.     char *addr;
  314. {
  315.  
  316.     if (addr < minsbrk)
  317.         addr = minsbrk;
  318.     asm("    chmk    $17");
  319.     asm("    jcc    1f");
  320.     asm("    jmp    cerror");
  321. asm("1:");
  322.     curbrk = addr;
  323.     return (0);
  324. }
  325. #endif
  326.  
  327. #ifdef sun4
  328. void
  329. __mcount(frompcindex, selfpc)
  330.     unsigned short *frompcindex;
  331.     char *selfpc;
  332. {
  333.     register struct tostruct    *top;    
  334.     register struct tostruct    *prevtop;
  335.     register long        toindex;
  336.  
  337.     /*
  338.      *    check that we are profiling
  339.      *    and that we aren't recursively invoked.
  340.      */
  341.     if (profiling) {
  342.     return;
  343.     }
  344.     profiling = 1;
  345.     /*
  346.      *    check that frompcindex is a reasonable pc value.
  347.      *    for example:    signal catchers get called from the stack,
  348.      *            not from text space.  too bad.
  349.      */
  350.     frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
  351.     if ((unsigned long)frompcindex > s_textsize) {
  352.     goto done;
  353.     }
  354.     frompcindex = &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
  355.     toindex = *frompcindex;
  356.     if (toindex == 0) {
  357.     /*
  358.      *    first time traversing this arc
  359.      */
  360.     toindex = ++tos[0].link;
  361.     if (toindex >= tolimit) {
  362.         goto overflow;
  363.     }
  364.     *frompcindex = toindex;
  365.     top = &tos[toindex];
  366.     top->selfpc = selfpc;
  367.     top->count = 1;
  368.     top->link = 0;
  369.     goto done;
  370.     }
  371.     top = &tos[toindex];
  372.     if (top->selfpc == selfpc) {
  373.     /*
  374.      *    arc at front of chain; usual case.
  375.      */
  376.     top->count++;
  377.     goto done;
  378.     }
  379.     /*
  380.      *    have to go looking down chain for it.
  381.      *    top points to what we are looking at,
  382.      *    prevtop points to previous top.
  383.      *    we know it is not at the head of the chain.
  384.      */
  385.     for (; /* goto done */; ) {
  386.     if (top->link == 0) {
  387.         /*
  388.          *    top is end of the chain and none of the chain
  389.          *    had top->selfpc == selfpc.
  390.          *    so we allocate a new tostruct
  391.          *    and link it to the head of the chain.
  392.          */
  393.         toindex = ++tos[0].link;
  394.         if (toindex >= tolimit) {
  395.         goto overflow;
  396.         }
  397.         top = &tos[toindex];
  398.         top->selfpc = selfpc;
  399.         top->count = 1;
  400.         top->link = *frompcindex;
  401.         *frompcindex = toindex;
  402.         goto done;
  403.     }
  404.     /*
  405.      *    otherwise, check the next arc on the chain.
  406.      */
  407.     prevtop = top;
  408.     top = &tos[top->link];
  409.     if (top->selfpc == selfpc) {
  410.         /*
  411.          *    there it is.
  412.          *    increment its count
  413.          *    move it to the head of the chain.
  414.          */
  415.         top->count++;
  416.         toindex = prevtop->link;
  417.         prevtop->link = top->link;
  418.         top->link = *frompcindex;
  419.         *frompcindex = toindex;
  420.         goto done;
  421.     }
  422.     }
  423. done:
  424.     profiling = 0;
  425.     return;
  426.  
  427. overflow:
  428.     profiling++; /* halt further profiling */
  429. #define    TOLIMIT    "mcount: tos overflow\n"
  430.     write(2, TOLIMIT, sizeof(TOLIMIT));
  431.     return;
  432. }
  433. #endif
  434.